package cn.edu.scut.hsrc.bean;

import java.util.ArrayList;
import java.util.List;

import cn.edu.scut.hsrc.bean.PhraseSegment.TitleFlag;
import cn.edu.scut.hsrc.bean.WordType.Type;
import cn.edu.scut.hsrc.output.Label;

/**
 * 候选短语类
 * @file CandidatePhrase.java
 * @author feiyu
 *
 */

public class CandidatePhrase implements Comparable<CandidatePhrase>{
	
	public static final int MAX_IMPURITY = 10000;	 //最大的杂质数
	
	private final SeqWord centerWord;				 //中心词
	private final List<SeqWord> seqWords;			 //短语包含的词
	private final List<Word> wordSet;				 //短语中的词集，记录短语中包含了哪些不同的词
	private final int nvCount;						 //短语包含动名词个数
	private double leftScore;						 //左独立性得分
	private double rightScore;						 //右独立性得分
	private double score;							 //短语得分（注意：这个和左右独立性得分不是同一个概念）
	private List<Integer> docs;						 //包含该短语的文档编号列表
	private List<PhraseSegment> phraseSegments; 	 //短语所在段的具体情况
	private List<PhraseSegment.TitleFlag> titleFlag; //该短语是从标题扩展得到的，还是从摘要得到的标识位，1为标题，0为摘要
	private final CandidateWord candidateWord;                    //用于标记该推荐短语属于哪一个社团；            
	
	/**
	 * 
	 * 构造函数
	 * @param centerWord	中心词
	 * @param seqWords		短语包含的词
	 * @param wordSet		短语中的词集
	 * @param nvCount		短语包含动名词个数
	 */
	public CandidatePhrase(SeqWord centerWord,List<SeqWord> seqWords,List<Word> wordSet,int nvCount,CandidateWord candidateWord) {
		// TODO Auto-generated constructor stub
		this.centerWord = centerWord;
		this.seqWords = seqWords;
		this.wordSet = wordSet;
		this.nvCount = nvCount;
		this.leftScore = this.rightScore = 0;
		this.score = 0;
		this.docs = new ArrayList<Integer>();
		this.phraseSegments = new ArrayList<PhraseSegment>();
		this.titleFlag = new ArrayList<PhraseSegment.TitleFlag>();
		this.candidateWord=candidateWord;
	}

	/**
	 * 获取中心词
	 * @return
	 */
	public Word getCenterWord() {
		return this.centerWord;
	}
	
	public CandidateWord getCandidateWord(){
		return this.candidateWord;
	}
	
	/**
	 * 返回短语中的词（这些词有顺序的）
	 * @return
	 */
	public List<SeqWord> getSeqWords() {
		return this.seqWords;
	}
	
	/**
	 * 获取短语中包含的词集（每个词都不一样）
	 * @return
	 */
	public List<Word> getWordSet() {
		return this.wordSet;
	}

	/**
	 * 获取短语包含动名词个数
	 * @return
	 */
	public int getNvCount() {
		return this.nvCount;
	}

	/**
	 * 获取左独立性得分
	 * @return
	 */
	public double getLeftScore() {
		return this.leftScore;
	}

	/**
	 * 获取右独立性得分
	 * @return
	 */
	public double getRightScore() {
		return this.rightScore;
	}

	/**
	 * 获取包含该短语的文档编号集合
	 * @return
	 */
	public List<Integer> getDocs() {
		return this.docs;
	}

	/**
	 * 设置左独立性得分
	 * @param leftScore
	 */
	public void setLeftScore(double leftScore) {
		this.leftScore = leftScore;
	}

	/**
	 * 设置右独立性得分
	 * @param rightScore
	 */
	public void setRightScore(double rightScore) {
		this.rightScore = rightScore;
	}
	
	/**
	 * 添加和该短语相关的文档编号，这里会进行去重
	 * @param docIndex
	 */
	public void addDoc(int docIndex) {
		if(docIndex >= 0 && this.docs.indexOf(docIndex) == -1)
			this.docs.add(docIndex);
	}
	
	/**
	 * 一次加入多个和该短语相关的文档比编号，这里会进行去重
	 * @param docIndexs
	 */
	public void addDocs(List<Integer> docIndexs) {
		if(docIndexs == null)
			return;
		for (Integer index : docIndexs) {
			if(this.docs.indexOf(index) == -1)
				this.docs.add(index);
		}
	}
	
	public Label getLabel() {
		String text = "";
		for (Word word : this.seqWords) {
			if(word.getType() != Type.BIAODIAN)
				text += word.getText();
		}
		return new Label(text,this.score);
	}
	
	/**
	 * 判断两个候选短语是否包含相同的词集（这个函数需要优化）
	 * @param candidatePhrase
	 * @return
	 */
	private boolean containSameWords(CandidatePhrase candidatePhrase)
	{
		if(candidatePhrase == null || this.wordSet.size() != candidatePhrase.wordSet.size())
			return false;
		//if(this.wordSet.size() == 0 || candidatePhrase.wordSet.size() == 0)
			//return false;
		for (Word word : candidatePhrase.wordSet) {
			if(!this.wordSet.contains(word))
				return false;
		}
		return true;
	}
	
	/**
	 * 返回该短语包含的词（不是词集）的个数
	 * @return
	 */
	public int count(){
		return this.seqWords.size();
	}
	
	/**
	 * 获取候选短语最左边的那个词
	 * @return 如果存在，就返回最左边的那个词，如果不存在，就返回null
	 */
	public Word getLeftWord() {
		if(this.seqWords.size() > 0)
			return this.seqWords.get(0);
		return null;
	}
	
	/**
	 * 获取候选短语最右边的那个词
	 * @return 如果存在，就返回最右边的那个词，如果不存在，就返回null
	 */
	public Word getRightWord() {
		int size = this.seqWords.size();
		if(size >0 )
			return this.seqWords.get(size-1);
		return null;
	}
	

	/**
	 * 判断两个候选短语是否相等，这里只是判断里面的词是否相等，只要求词集是一样的
	 */
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(obj instanceof CandidatePhrase)
		{
			return containSameWords((CandidatePhrase)obj);
		}
		return false;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		String text = "";
		for (Word word : this.seqWords) {
			text += ","+word.getText();
		}
		if(text.length() > 0)
			text = text.substring(1);
		
		text += "\t>>>>>\t";
		for (Word word : this.wordSet) {
			text += word.getText()+",";
		}
		return text+"\n";
	}

	@Override
	public int compareTo(CandidatePhrase phrase) {
		// TODO Auto-generated method stub
		if(this.score > phrase.score)
			return -1;
		else if(this.score < phrase.score)
			return 1;
		else return 0;
	}

	/**
	 * 获取所有的分段信息
	 * @return
	 */
	public List<PhraseSegment> getPhraseSegments() {
		return this.phraseSegments;
	}
	
	public List<TitleFlag> getTitleFlags() {
		return this.titleFlag;
	}
	
	/**
	 * 获取下标为index的分段信息
	 * @param index
	 * @return
	 */
	public PhraseSegment getPhraseSegment(int index)
	{
		return this.phraseSegments.get(index);
	}
	
	/**
	 * 
	 * @param index
	 * @return
	 */
	public TitleFlag getTitleFlag(int index) {
		return this.titleFlag.get(index);
	}
	
	/**
	 * 设置分段信息
	 * @param phraseSegments
	 */
	public void setPhraseSegments(List<PhraseSegment> phraseSegments) {
		this.phraseSegments = phraseSegments;
	}
	
	/**
	 * 设置下标index对应的那个集合的分段信息为segments
	 * @param index
	 * @param segments
	 */
	public void setPhraseSegment(int index,PhraseSegment segments)
	{
		this.phraseSegments.set(index, segments);
	}
	
	/**
	 * 添加段信息
	 * @param segments
	 */
	public void addPhraseSegment(PhraseSegment segments) {
		if(segments == null)
			return;
		this.phraseSegments.add(segments);
	}
	
	/**
	 * 添加标题标识位
	 * @param flag
	 */
	public void addTitleFlag(TitleFlag flag) {
		this.titleFlag.add(flag);
	}
	
	/**
	 * 设置标题标识位
	 * @param index
	 * @param flag
	 */
	public void  setTitleFlag(int index,TitleFlag flag) {
		this.titleFlag.set(index, flag);
	}

	/**
	 * 
	 * @return
	 */
	public double getScore() {
		return this.score;
	}

	/**
	 * 
	 * @param score
	 */
	public void setScore(double score) {
		this.score = score;
	}
}

